const path = require('path')
const fs = require('fs')
module.exports = class TestCode {
    /**
     * 批量生成测试文件以及代码
     * @param {*} filePath 需要生成__tests__的文件路径，默认取值当前文件目录下
     */
    createTestSource(filePath = path.resolve('./')) {
        const testPath = `${filePath}/__tests__`
        if (!fs.existsSync(testPath)) {
            fs.mkdirSync(testPath)
        }
        const list = fs.readdirSync(filePath) // 返回当前文件夹目录下所有的文件名数组
        list
            // 根据list生成完整路径数组,方便读取
            .map(v => `${filePath}/${v}`)
            // 判断是文件还是文件夹 以及排除 spec文件
            .filter(v => fs.statSync(v).isFile() && v.indexOf('.spec') === -1)
            // 最后调用生成方法
            .map(v => this.genTestFile(v))
    }

    /**
     * 生成文件，并写测试代码进去
     * @param {*} fileFullPath 文件完整路径
     */
    genTestFile(fileFullPath) {
        // 生成测试路径文件名
        const testFileName = this.getTestName(fileFullPath)
        if (fs.existsSync(testFileName)) {
            console.log('已经存在测试文件', testFileName)
            return
        }
        // 引入文件
        const mod = require(fileFullPath)
        let sourse = ''
        if (typeof mod === 'object') {
            sourse = Object.keys(mod).map(v => this.getTestSource(v, path.basename(fileFullPath), true)).join('\n')
        } else if (typeof mod === 'function') {
            const baseName = path.basename(fileFullPath)
            sourse = this.getTestSource(baseName.replace('.js', ''), baseName)
        }
        fs.writeFileSync(testFileName, sourse)
    }

    /**
     * 生成测试文件的代码内容
     * @param {*} methordName 测试方法的名称
     * @param {*} classFile 测试文件名称
     * @param {*} isClass 判断是class还是function
     */
    getTestSource(methordName, classFile, isClass = false) {
        return `
        test('测试${methordName}', () => {
            const ${isClass ? '{' + methordName + '}' : methordName} = require('../${classFile}')
            const ret = ${methordName}()
            // expect(ret)
            //  .toBe('/abc/__tests__/index.spec.js')
        })
        `
    }

    /**
     * 生成测试文件名称
     * @param {*} name 代码文件名
     */
    getTestName(name) {
        const dirPath = path.dirname(name) // 返回除了baseName剩余的部分
        const baseName = path.basename(name) // 返回 path 的最后一部分 如index.js
        const extName = path.extname(name) // 返回path路径文件扩展名 .js .html
        const textName = baseName.replace(extName, `.spec${extName}`)
        return path.format({
            root: dirPath + '/__tests__/',
            base: textName
        })
    }
}